package gnss

import (
	"dgo/goutils/utils"
	"math"
)

/** SSR High Rate Clock Correction, 暂未使用 */
type IgsSSR_IGM_IFPB struct {
	SatId   byte
	IFPB    float64
	IFPB_T0 float64
}

type IgsSSR_IGM_IFPB_List [SATID_MAX]IgsSSR_IGM_IFPB

func (this *IgsSSR_IGM_IFPB_List) Count() int {
	r := 0
	for i := 0; i < len(this); i++ {
		rec := this[i]
		if rec.SatId != 255 && rec.SatId != 0 {
			r++
		}
	}
	return r
}

func (this *IgsSSR_IGM_IFPB_List) CheckGetSat(satid byte) *IgsSSR_IGM_IFPB {
	sat := &this[satid-1]
	if sat.SatId != satid {
		sat.SatId = satid
	}
	return sat
}

func EncodeIgsIGM_IFPB(head *IgsSSRHead, lst *IgsSSR_IGM_IFPB_List, bb *utils.BytesBuilder, startByteN int) int {
	satn := uint32(lst.Count())
	var startBitN int = 0
	head.MsgID = 4076
	if head.NaviSys == SYS_GPS {
		startBitN = head.EncodeIGM_IFPBHead(bb, startByteN, 161, satn)
	} else if head.NaviSys == SYS_GLO {
		startBitN = head.EncodeIGM_IFPBHead(bb, startByteN, 44, satn)
	} else if head.NaviSys == SYS_BD {
		startBitN = head.EncodeIGM_IFPBHead(bb, startByteN, 104, satn)
	} else if head.NaviSys == SYS_GAL {
		startBitN = head.EncodeIGM_IFPBHead(bb, startByteN, 64, satn)
	} else if head.NaviSys == SYS_QZS {
		startBitN = head.EncodeIGM_IFPBHead(bb, startByteN, 84, satn)
	}
	startBitN = EncodeIGM_IFPBSat(head, lst, bb, startByteN, startBitN)
	byteN := int(math.Ceil(float64(startBitN) / 8))
	bb.Delete2End(startByteN + byteN)
	return byteN
}

func EncodeRtcmIgsIGM_IFPB(head *IgsSSRHead, lst *IgsSSR_IGM_IFPB_List, bb *utils.BytesBuilder) {
	idx0 := bb.Len()
	bb.Write([]byte{0xD3, 0, 0})
	ByteN := EncodeIgsIGM_IFPB(head, lst, bb, bb.Len())
	bb.SetBitU16(idx0, 8+6, 10, uint16(ByteN))

	bb.CheckSize(bb.Len(), 3)
	crcBuf := bb.Buff(idx0, ByteN+3) // 3:同步标记 + 保留位 + 长度（RTCM消息体）(10bit)
	crc1 := utils.CRC24QBuf(crcBuf)
	bb.SetBitU32(idx0+3+ByteN, 0, 24, uint32(crc1))
	bb.Delete2End(idx0 + 3 + ByteN + 3)
}

func EncodeIGM_IFPBSat(head *IgsSSRHead, lst *IgsSSR_IGM_IFPB_List, bb *utils.BytesBuilder, startByteN int, startBitN int) int {
	for i := 0; i < len(lst); i++ {
		sat := lst[i]
		if sat.SatId > 0 && sat.SatId != 255 {

			bb.CheckSize(startByteN, (startBitN+48)/8+1)
			// GNSS Satellite ID
			bb.SetBitU8(startByteN, startBitN, 6, byte(sat.SatId))
			startBitN += 6

			/* IFPB */
			v := sat.IFPB / 1e-4
			bb.SetBitI32(startByteN, startBitN, 22, int32(math.Round(v)))
			startBitN += 22

			/* IFPB_T0 */
			v = sat.IFPB_T0
			bb.SetBitU32(startByteN, startBitN, 20, uint32(math.Round(v)))
			startBitN += 20
		}
	}

	return startBitN
}
